import ReconnectingWebSocket from 'reconnecting-websocket'
import { getToken } from '@/api/user.js'

const NOTIFICATION_TYPE = ['info', 'success', 'warning', 'error']

export default {
  data() {
    return {
      ws: null,
      heartbeat: {
        interval: 30000, // 心跳间隔30秒
        serverTimeout: 30000, // 服务器响应超时30秒
        timeoutId: null, // 心跳定时器ID
        retryCount: 0, // 当前重试次数
        maxRetries: 3, // 最大重试次数
        lastResponseTime: null // 最后收到响应的时间
      }
    }
  },
  methods: {
    // 初始化WebSocket连接
    initWebsocket() {
      getToken().then(token => {
        if (!token) {
          this.$Message.warning('同步登录3.0系统失败，请联系管理员排查')
          return
        }

        this.closeWebsocket() // 清理旧连接

        const url = location.hostname
        // eslint-disable-next-line max-len
        this.ws = new ReconnectingWebSocket(`ws://${url}/tfws/websocket/${token}?systemName=二进制内部系统&nickName=${this.$store?.state?.user?.userInfo?.nickName}`)

        // 添加事件监听
        this.ws.addEventListener('open', this.handleOpen)
        this.ws.addEventListener('message', this.handleMessage)
        this.ws.addEventListener('close', this.handleClose)
        this.ws.addEventListener('error', this.handleError)
      })
    },

    // 清理连接
    cleanUpConnection() {
      if (this.heartbeat.timeoutId) {
        clearInterval(this.heartbeat.timeoutId)
        this.heartbeat.timeoutId = null
      }
      if (this.ws) {
        // 移除所有事件监听
        this.ws.removeEventListener('open', this.handleOpen)
        this.ws.removeEventListener('message', this.handleMessage)
        this.ws.removeEventListener('close', this.handleClose)
        this.ws.removeEventListener('error', this.handleError)
      }
    },

    // 连接打开处理
    handleOpen() {
      // 发送初始消息
      this.ws.send(JSON.stringify({ notificationType: 0, msgLevel: 0 }))

      // 初始化心跳检测
      this.heartbeat.lastResponseTime = Date.now()
      this.heartbeat.timeoutId = setInterval(this.checkHeartbeat, this.heartbeat.interval)
      this.heartbeat.retryCount = 0 // 重置重试计数器
    },

    // 消息接收处理
    handleMessage({ data }) {
      console.log('接收到信息')
      try {
        const obj = JSON.parse(data)

        // 更新最后响应时间
        this.heartbeat.lastResponseTime = Date.now()
        this.heartbeat.retryCount = 0 // 收到任何有效消息都重置计数器

        this.processMessage(obj)
      } catch (error) {
        console.error('解析WebSocket消息失败:', error)
      }
    },

    // 处理不同类型的消息
    processMessage(obj) {
      console.log('信息内容', obj)
      if (!obj) return

      const { msg, notificationType } = obj

      // 跳过心跳
      if (notificationType === 0) {
        return
      }

      // 需要触发页面刷新的通知类型
      const refreshTypes = [109, 108, 100, 111, 112, 110, 105, 106, 107, 113]
      if (refreshTypes.includes(notificationType)) {
        this.$store.commit('board/setRefreshNotice')
        // notificationType === 110 为3.0测试报告信息，二进制不显示弹框
        if (notificationType !== 110) {
          this.showNotification(obj, msg)
        }
      }
    },

    // 显示通知
    showNotification(obj, msg) {
      let msgLevel = obj?.msgLevel?.toLowerCase()
      console.log('展示公告', msgLevel, msg)
      if (!NOTIFICATION_TYPE.includes(msgLevel)) {
        msgLevel = 'info'
      }

      let notice = ''
      try {
        notice = JSON.parse(msg)
      } catch (error) {
        notice = msg
      }

      const desc = typeof notice === 'object' ? notice.msg : notice
      // 无法正常解析到数据，不发通知，避免出现空的公告
      if (!desc) {
        return
      }

      this.$Notice[msgLevel]({
        title: '通知',
        desc,
        duration: 20
      })
    },

    // 心跳检测
    checkHeartbeat() {
      const timeSinceLastResponse = Date.now() - this.heartbeat.lastResponseTime

      // 如果超过超时时间未收到响应
      if (timeSinceLastResponse > this.heartbeat.serverTimeout) {
        this.heartbeat.retryCount++

        // 达到最大重试次数，重新连接
        if (this.heartbeat.retryCount >= this.heartbeat.maxRetries) {
          console.warn(`心跳检测失败，已重试${this.heartbeat.retryCount}次，正在重新连接...`)
          this.initWebsocket()
          return
        }

        console.warn(`心跳未响应(第${this.heartbeat.retryCount}/${this.heartbeat.maxRetries}次)`)
      }

      // 发送心跳包
      console.log('发送心跳包')
      this.ws.send(JSON.stringify({ notificationType: 0, msgLevel: 0, msg: 'ping' }))
    },

    // 连接关闭处理
    handleClose() {
      this.cleanUpConnection()
      console.log('WebSocket连接已关闭')
    },

    // 连接错误处理
    handleError() {
      this.cleanUpConnection()
      console.error('WebSocket连接错误')
    },

    // 主动关闭连接
    closeWebsocket() {
      this.cleanUpConnection()
      this.ws && this.ws.close()
    },

    // 页面可见性变化时重连
    resetWebSocket() {
      if (document.visibilityState === 'visible') {
        // 页面重新可见，判断websocket连接是否还存在
        if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
          this.initWebsocket()
        }
      }
    }
  },
  mounted() {
    this.initWebsocket()
    document.addEventListener('visibilitychange', this.resetWebSocket)
  },
  beforeDestroy() {
    this.closeWebsocket()
    document.removeEventListener('visibilitychange', this.resetWebSocket)
  }
}
